package com.weixin.tools;


import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import com.weixin.bo.oauth.RecevieOauth2Token;
import com.weixin.bo.oauth.RecevieSNSUserInfo;
import com.alibaba.fastjson.JSONObject;
import com.fh.util.Logger;

public class ToolOAuth2 {

	private static Logger log = Logger.getLogger(ToolOAuth2.class);
	
	/**
	 * 用户同意授权，获取code
	 * snsapi_base（不弹出授权页面，只能拿到用户openid）
	 * snsapi_userinfo（弹出授权页面，这个可以通过 openid 拿到昵称、性别、所在地）
	 * @param appId
	 * @param redirectUri
	 * @return
	 */
	public static String getOauth2Code(String appId, String redirectUri) {
		    try {
				Map<String, String> params = new HashMap<String, String>();
				params.put("appid", appId);
				params.put("response_type", "code");
				params.put("redirect_uri", redirectUri.trim());
				params.put("scope", "snsapi_base"); 
				params.put("state", "wx#wechat_redirect");
				String para = createSign(params, true);
				
				// 拼接请求地址
				String requestUrl = "http://open.weixin.qq.com/connect/oauth2/authorize";
				return requestUrl =requestUrl + "?" + para;
			} catch (UnsupportedEncodingException e) {
				log.error("ToolOAuth.getOauth2Code获取网页code异常，appId：" + appId + " redirectUri：" + redirectUri );
				return null;
			}
		
	}
	
	
	/**
	 * 获取网页授权凭证
	 * 
	 * @param appId 公众账号的唯一标识
	 * @param appSecret 公众账号的密钥
	 * @param code
	 * @return WeixinAouth2Token
	 */
	public static RecevieOauth2Token getOauth2AccessToken(String appId, String appSecret, String code) {
		// 拼接请求地址
		String requestUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";
		requestUrl = requestUrl.replace("APPID", appId);
		requestUrl = requestUrl.replace("SECRET", appSecret);
		requestUrl = requestUrl.replace("CODE", code);
		// 获取网页授权凭证
		try {
			String jsonStr = ToolHttp.get(true, requestUrl);
			JSONObject object=JSONObject.parseObject(jsonStr);
			
			RecevieOauth2Token rec=new RecevieOauth2Token();
			rec.setAccessToken(object.getString("access_token"));
			rec.setOpenId(object.getString("openid"));
			rec.setExpiresIn(object.getInteger("expires_in"));
			rec.setRefreshToken(object.getString("refresh_token"));
			rec.setScope(object.getString("scope"));
			
			
			return rec;
		} catch (Exception e) {
			log.error("ToolOAuth.getOauth2AccessToken获取网页授权凭证异常，appId：" + appId + " appSecret：" + appSecret + " code：" + code);
			return null;
		}
	}

	/**
	 * 刷新网页授权凭证
	 * 
	 * @param appId 公众账号的唯一标识
	 * @param refreshToken
	 * @return WeixinAouth2Token
	 */
	public static RecevieOauth2Token refreshOauth2AccessToken(String appId, String refreshToken) {
		// 拼接请求地址
		String requestUrl = "https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=APPID&grant_type=refresh_token&refresh_token=REFRESH_TOKEN";
		requestUrl = requestUrl.replace("APPID", appId);
		requestUrl = requestUrl.replace("REFRESH_TOKEN", refreshToken);
		// 刷新网页授权凭证
		try {
			String jsonStr = ToolHttp.get(true, requestUrl);
			JSONObject object=JSONObject.parseObject(jsonStr);
			
			RecevieOauth2Token rec=new RecevieOauth2Token();
			rec.setAccessToken(object.getString("access_token"));
			rec.setOpenId(object.getString("openid"));
			rec.setExpiresIn(object.getInteger("expiresin"));
			rec.setRefreshToken(object.getString("refreshtoken"));
			rec.setScope(object.getString("scope"));
			
			return rec;
		} catch (Exception e) {
			log.error("ToolOAuth.refreshOauth2AccessToken刷新网页授权凭证异常，appId：" + appId + " refreshToken：" + refreshToken);
			return null;
		}
	}
	
	/**
	 * 通过网页授权获取用户信息
	 * 
	 * @param accessToken 网页授权接口调用凭证
	 * @param openId 用户标识
	 * @return SNSUserInfo
	 */
	public static RecevieSNSUserInfo getSNSUserInfo(String accessToken, String openId) {
		// 拼接请求地址
		String requestUrl = "https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID";
		requestUrl = requestUrl.replace("ACCESS_TOKEN", accessToken).replace("OPENID", openId);
		// 通过网页授权获取用户信息
		try {
			String jsonStr = ToolHttp.get(true, requestUrl);
			JSONObject object=JSONObject.parseObject(jsonStr);
			RecevieSNSUserInfo snsUserInfo = new RecevieSNSUserInfo();
			snsUserInfo.setHeadImgUrl(object.getString("headimgurl"));
			snsUserInfo.setOpenId(object.getString("openid"));
			snsUserInfo.setCity(object.getString("city"));
			snsUserInfo.setCountry(object.getString("country"));
			snsUserInfo.setNickname(object.getString("nickname"));
//			if(StringUtils.isNotBlank(object.getString("privilege"))){
//				snsUserInfo.setPrivilegeList(object.parseArray("privilege",String.class));
//			}
			snsUserInfo.setProvince(object.getString("province"));
			snsUserInfo.setSex(object.getInteger("sex"));
			snsUserInfo.setLanguage(object.getString("language"));
			
			return snsUserInfo;
		} catch (Exception e) {
			log.error("ToolOAuth.getSNSUserInfo通过网页授权获取用户信息异常，accessToken：" + accessToken + " openId：" + openId);
			return null;
		}
	}

	/**
	 * 通过网页授权获取jsapi接口
	 * @param accessToken 网页授权接口调用凭证
	 */
	public static String getJsApiToken(String accessToken) {
		// 拼接请求地址
		String requestUrl = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi";
		requestUrl = requestUrl.replace("ACCESS_TOKEN", accessToken);
		String jsapi_ticket = "";

		// 通过网页授权获取用户信息
		try {
			String jsonStr = ToolHttp.get(true, requestUrl);

			JSONObject jsonObject = JSONObject.parseObject(jsonStr);
			jsapi_ticket=(String) jsonObject.get("ticket");
			
			return jsapi_ticket;
		} catch (Exception e) {
			log.error("ToolOAuth.getJsApiToken通过网页授权获取jsapi接口异常，accessToken：" + accessToken);
			return jsapi_ticket;
		}
	}

	 /**
     * 构造签名
     * @param params
     * @param encode
     * @return
     * @throws UnsupportedEncodingException 
     */
    public static String createSign(Map<String, String> params, boolean encode) throws UnsupportedEncodingException {
        Set<String> keysSet = params.keySet();
        Object[] keys = keysSet.toArray();
        Arrays.sort(keys);
        StringBuffer temp = new StringBuffer();
        boolean first = true;
        for (Object key : keys) {
            if (first) {
                first = false;
            } else {
                temp.append("&");
            }
            temp.append(key).append("=");
            Object value = params.get(key);
            String valueString = "";
            if (null != value) {
                valueString = value.toString();
            }
            if (encode) {
                temp.append(URLEncoder.encode(valueString, "UTF-8"));
            } else {
                temp.append(valueString);
            }
        }
        return temp.toString();
    }
}
